package com.aloda.aop;

import com.alibaba.fastjson.JSONObject;
import com.aloda.annotation.LoginLogAnno;
import com.aloda.context.NetUtils;
import com.aloda.entity.LoginLog;
import com.aloda.mapper.LoginLogMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Objects;

@Aspect
@Component
public class LoginLogAspect {

    @Resource
    private LoginLogMapper loginLogMapper;

    @Around("@annotation(loginLogAnno)")
    public Object writeLoginLog(ProceedingJoinPoint joinPoint, LoginLogAnno loginLogAnno) throws Throwable {
        LocalDateTime time = LocalDateTime.now();
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
        String remoteHost = NetUtils.getIpAddress(httpServletRequest);
        // 获取描述
        String userAgent = httpServletRequest.getHeader("User-Agent");
        // 获取操作的方法名
        String methodName = joinPoint.getSignature().getName();
        // 操作方法的参数
        Object[] args = joinPoint.getArgs();
        String methodParams = encryptArgs(args[0]);
        Object result = joinPoint.proceed();
        // 方法返回值
        String returnValue = JSONObject.toJSONString(encryptArgs(result));
        LoginLog loginLog = new LoginLog();
        loginLog.setLoginTime(time);
        loginLog.setLoginIp(remoteHost);
        loginLog.setLoginDesc(userAgent + "__" + loginLogAnno.desc());
        loginLog.setMethodName(methodName);
        loginLog.setMethodParams(methodParams);
        loginLog.setReturnValue(returnValue);
        loginLogMapper.insert(loginLog);
        return result;
    }

    /**
     * 加密参数：将第一个逗号后面的所有内容替换为 "***"
     *
     * @param args 输入参数数组
     * @return 加密后的字符串
     */
    private static String encryptArgs(Object args) {
        // 判断参数是否为空或长度为 0，如果是，则返回空字符串
        if (args == null) {
            return "";
        }

        // 将第一个参数转换为字符串（因为输入是 Object[]，需要使用 Objects.toString 进行安全转换）
        String input = Objects.toString(args, "");

        // 查找第一个逗号的位置
        int firstCommaIndex = input.indexOf(",");

        // 如果没有找到逗号，直接返回原始字符串
        if (firstCommaIndex == -1) {
            return input;
        }

        // 截取第一个逗号之前的部分，并将逗号后面的内容替换为 "***"
        return input.substring(0, firstCommaIndex + 1) + "...";
    }
}